package com.xjtu.mybatisplus.service.impl.review;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xjtu.mybatisplus.common.JsonResponse;
//import com.xjtu.mybatisplus.common.JsonResponse.PageJsonResponse;
//import com.xjtu.mybatisplus.common.JsonResponse.JsonResponse;

import com.xjtu.mybatisplus.common.result.PageResult;
import com.xjtu.mybatisplus.mapper.ArticleMapper;
import com.xjtu.mybatisplus.mapper.SubscribeMapper;
import com.xjtu.mybatisplus.mapper.UserMapper;
import com.xjtu.mybatisplus.model.domain.Article;
import com.xjtu.mybatisplus.model.domain.Review;
import com.xjtu.mybatisplus.mapper.ReviewMapper;
import com.xjtu.mybatisplus.model.domain.Subscribe;
import com.xjtu.mybatisplus.model.domain.User;
import com.xjtu.mybatisplus.model.dto.ReviewDto;
import com.xjtu.mybatisplus.model.vo.SubNoticeVo;
import com.xjtu.mybatisplus.model.vo.reviewVo.ReviewStaticVo;
import com.xjtu.mybatisplus.model.vo.reviewVo.ReviewVo;
import com.xjtu.mybatisplus.model.vo.reviewVo.ReviewerVo;
import com.xjtu.mybatisplus.service.ReviewService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjtu.mybatisplus.service.SubscribeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lsong
 * @since 2023-12-27
 */
@Service
@Slf4j
//@Transactional
public class ReviewServiceImpl extends ServiceImpl<ReviewMapper, Review> implements ReviewService {

    @Value("${review.phaseNum}")
    Integer phaseNum;

    @Value("${review.threshold}")
    Integer threshold;

    @Autowired
    ReviewMapper reviewMapper;

    @Autowired
    ArticleMapper articleMapper;

    @Autowired
    UserMapper userMapper;



    @Autowired
    SubscribeMapper subscribeMapper;
//    QueryWrapper<Article> articleQueryWrapper = new QueryWrapper<>();

    @Autowired
    SubscribeService subscribeService;

    @Override
    public JsonResponse<PageResult> getTaskById(Long reviewId, Integer page, Integer pageSize) {

        QueryWrapper<Review> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Review::getUserId, reviewId);

//        articleQueryWrapper.select("title").eq("id", )

        // 使用 page 方法执行分页查询
        Page<Review> reviewPage = this.page(new Page<>(page, pageSize), wrapper);
        // 将查询结果进行转换，将 Review 转换为 ReviewVo
        IPage<ReviewVo> reviewVoPage = reviewPage.convert(
                review -> {
                    // 这里是转换函数，将 Review 转换为 ReviewVo
                    ReviewVo reviewVo = new ReviewVo();

//                    log.info("审核信息：{}", review);
                    BeanUtils.copyProperties(review, reviewVo);


                    //联表 暂时不知道怎么办
                    Article article = articleMapper.selectById(review.getArticleId());
                    if(article != null) {
                        reviewVo.setTitle(article.getTitle());
                        reviewVo.setAuthor(article.getAuthor());
                        User user = userMapper.selectById(review.getUserId());
                        reviewVo.setUsername(user.getUsername());
                    }
                    //

                    log.info("审核信息：{}", reviewVo);
                    // 进行属性赋值
                    // reviewVo.setXXX(review.getXXX());
                    return reviewVo;
                }
        );

        // 构建 PageJsonResponse 对象并设置 total 和 items
        PageResult pageJsonResponse = new PageResult();
        log.info("条数：{}", reviewVoPage.getTotal());
        log.info("记录：{}", reviewVoPage.getRecords());
        pageJsonResponse.setTotal(reviewVoPage.getTotal());
        pageJsonResponse.setItems(reviewVoPage.getRecords());

        return JsonResponse.success(pageJsonResponse);
    }

    @Override
    public JsonResponse<PageResult> getAllTask(Integer page, Integer pageSize) {
        QueryWrapper<Review> wrapper = new QueryWrapper<>();


        // 使用 page 方法执行分页查询
        Page<Review> reviewPage = this.page(new Page<>(page, pageSize), wrapper);
        // 将查询结果进行转换，将 Review 转换为 ReviewVo
        IPage<ReviewVo> reviewVoPage = reviewPage.convert(
                review -> {
                    // 这里是转换函数，将 Review 转换为 ReviewVo
                    ReviewVo reviewVo = new ReviewVo();
//                    log.info("审核信息：{}", review);
                    BeanUtils.copyProperties(review, reviewVo);

                    //联表 暂时不知道怎么办
                    Article article = articleMapper.selectById(review.getArticleId());
                    if(article != null) {
                        reviewVo.setTitle(article.getTitle());
                        reviewVo.setAuthor(article.getAuthor());
                        User user = userMapper.selectById(review.getUserId());
                        if(user == null) {
                            reviewVo.setUsername("无");
                        } else {
                            reviewVo.setUsername(user.getUsername());
                        }
//                        log.info("user为：{}", user);

                    }
                    //

                    log.info("审核信息：{}", reviewVo);
                    // 进行属性赋值
                    // reviewVo.setXXX(review.getXXX());
                    return reviewVo;
                }
        );

        // 构建 PageJsonResponse 对象并设置 total 和 items
        PageResult pageJsonResponse = new PageResult();
        log.info("条数：{}", reviewVoPage.getTotal());
        log.info("记录：{}", reviewVoPage.getRecords());
        pageJsonResponse.setTotal(reviewVoPage.getTotal());
        pageJsonResponse.setItems(reviewVoPage.getRecords());

        return JsonResponse.success(pageJsonResponse);
    }

    @Override
    public JsonResponse update(ReviewDto reviewDto) {
        log.info("传入review为：{}",reviewDto );
        Review review = new Review();
        BeanUtils.copyProperties(reviewDto, review);
        log.info("转换后review为：{}",review );
       if(reviewMapper.updateById(review) > 0 ){
           QueryWrapper<Article> wrapper = new QueryWrapper<>();
           wrapper.eq("id", review.getArticleId());
           Article article = articleMapper.selectOne(wrapper);

           log.info("phaseNum: {}", phaseNum);
           log.info("nowPhase: {}",review.getPhase());
           if(review.getResult() == 1) {
               article.setStatus(-1);

           } else {
               if(review.getPhase() < phaseNum){
                   log.info("文章审核通过第{}阶段",  review.getPhase());
                   insert(review.getArticleId(), (review.getPhase() + 1));
               } else {
                  if(generateNotice(article.getId())){
                      log.info("文章发布消息发送成功");
                  };
               }
               article.setStatus(review.getPhase());
           }

           articleMapper.updateById(article);
           return JsonResponse.success("");
       }else {
           return JsonResponse.failure("审核更新错误");
       }
    }


    public JsonResponse insert(Long articleId, Integer phase){
        Review review = new Review();
        review.setArticleId(articleId).setPhase(phase);
        if(reviewMapper.insert(review) > 0 ) {
            if(this.assignReview()) {
                log.info("系统分配成功");
            }
            return JsonResponse.success("");
        }
        return JsonResponse.failure("生成审核记录失败，请重新提交");
    }


    @Override
    public boolean assignReview() {
        List<Review> reviews = this.getUnreviewList();


        if(reviews.size() > threshold) {
            for(int i = 0; i < (reviews.size() - threshold); i++) {
                reviews.get(i).setUserId(getReviewer());
                if(reviewMapper.updateById(reviews.get(i))> 0) {
                    log.info("审核内容{}更新",reviews.get(i));
                } else {
                    log.info("更新失败");
                }
            }
        }
        return true;
    }

    @Override
    public JsonResponse applyReview(Long reviewId) {
        List<Review> reviews = this.getUnreviewList();
        if(reviews.size() == 0) {
            return JsonResponse.success(-1);
        }
        int index = 0;
        while(index < reviews.size()) {
        QueryWrapper<Review> reviewQueryWrapper = new QueryWrapper<>();
            reviewQueryWrapper.eq("user_id", reviewId).eq("article_id", reviews.get(index).getArticleId());
            if(reviewMapper.selectCount(reviewQueryWrapper) != 0 ) {
                index++;
                continue;
            }
            reviews.get(index).setUserId(reviewId);
            break;
        }
        if(index >= reviews.size()) {
            return JsonResponse.success(0);
        }
//        reviews.get(0).setUserId(reviewId);
        return reviewMapper.updateById(reviews.get(index)) > 0 ? JsonResponse.success(1) : JsonResponse.failure("没分配成功");
    }

    @Override
    public List<Review> getUnreviewList() {
        QueryWrapper<Review> reviewQueryWrapper = new QueryWrapper<>();
        reviewQueryWrapper.eq("user_id", -1);
        return reviewMapper.selectList(reviewQueryWrapper);
    }

    @Override
    public Long getReviewer() {
        return reviewMapper.findMinOccurrenceUserIdReview();

    }

    @Override
    public JsonResponse<Article> getArticle(Long articleId) {
//        Wrapper<Article> wrapper = new QueryWrapper<>();
        Article article = articleMapper.selectById(articleId);
        log.info("获取文章内容成功！");
        return JsonResponse.success(article);
    }

    @Override
    public JsonResponse<List<ReviewVo>> getUndoList(Long reviewId) {
        QueryWrapper<Review> wrapper = new QueryWrapper<>();
        if(reviewId == -1) {
            wrapper.eq("result", -1);
        }else {
            wrapper.eq("result", -1).eq("user_id", reviewId);
        }


        List<Review> reviews = reviewMapper.selectList(wrapper);
        List<ReviewVo> reviewVos = new ArrayList<>();
        if(reviews.size() == 0) return JsonResponse.success(null,"没有未完成的任务了");
        for(Review review : reviews) {
            ReviewVo reviewVo = new ReviewVo();
            BeanUtils.copyProperties(review, reviewVo);



            Article article = articleMapper.selectById(review.getArticleId());
            if(article != null) {
                reviewVo.setTitle(article.getTitle());
            }
            reviewVos.add(reviewVo);
            //

            log.info("审核信息：{}", reviewVo);
            // 进行属性赋值
            // reviewVo.setXXX(review.getXXX());

        }
        log.info("审核员{}的未审核任务已获取！", reviewId);
        return JsonResponse.success(reviewVos);



    }

    @Override
    public boolean resetReview(Long articleId) {
        QueryWrapper<Review> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("article_id", articleId);
        int delete = reviewMapper.delete(queryWrapper);
        return delete > 0;
    }

    @Override
    public JsonResponse<List<ReviewerVo>> getReviewerList() {
        QueryWrapper<Review> wrapper = new QueryWrapper<>();
        wrapper.select("user_id","COUNT(user_id) AS count").groupBy("user_id");
        List<Map<String, Object>> maps = listMaps(wrapper);
        if(maps.size() == 0) return JsonResponse.failure("未查询到审核人员");
        List<ReviewerVo> reviewerVos = new ArrayList<>();
        for(Map<String, Object>item : maps){
            if((Long)item.get("user_id") == -1) continue;
            reviewerVos.add(new ReviewerVo((Long)item.get("user_id"), (Long)item.get("count")));
        }

        log.info("审核员：{}", reviewerVos);
        for(ReviewerVo reviewerVo : reviewerVos) {
            Long reviewerId = reviewerVo.getUserId();
//            QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
//            userQueryWrapper.select("username").eq("username", reviewerId);
            User user = userMapper.selectById(reviewerId);
            reviewerVo.setUsername(user.getUsername());
        }

        return JsonResponse.success(reviewerVos);
    }

    @Override
    public JsonResponse<ReviewStaticVo> getStatic(Long reviewId) {
        ReviewStaticVo reviewStaticVo = new ReviewStaticVo();

        if(reviewId == -1) {
            log.info("=====================#管理员#==================");
            reviewStaticVo.setTotal(this.list().size());
            reviewStaticVo.setFinish(reviewMapper.selectCount(new QueryWrapper<Review>().ne("result", -1)));


            QueryWrapper<Review> wrapper = new QueryWrapper<>();
            wrapper.between("review_time", LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0),LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0).plusDays(1) );
//            reviewStaticVo.setTotalToday(reviewMapper.selectCount(wrapper));
            wrapper.ne("result", -1);
            reviewStaticVo.setFinishToday(reviewMapper.selectCount(wrapper));


            for(int i = 7; i>=1; i--) {
            List<String> time = getTimeRange(i);
            QueryWrapper<Review> wrapper1 = new QueryWrapper<>();
            wrapper1.between("review_time", time.get(0), time.get(1)).ne("result", -1);
            reviewStaticVo.getFinishSeven().add(reviewMapper.selectCount(wrapper1));
                log.info("=====================#管理员#==================");
                log.info("第{}天，{}", 8-i, reviewStaticVo.getFinishSeven());
            }
        } else {
            QueryWrapper<Review> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id", reviewId);
            reviewStaticVo.setTotal(reviewMapper.selectCount(wrapper));
            wrapper.ne("result", -1);
            reviewStaticVo.setFinish(reviewMapper.selectCount(wrapper));

            QueryWrapper<Review> wrapper1 = new QueryWrapper<>();
            wrapper1.eq("user_id",reviewId).between("review_time", LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0),LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0).plusDays(1) );
//            reviewStaticVo.setTotalToday(reviewMapper.selectCount(wrapper));
            wrapper1.ne("result", -1);
            reviewStaticVo.setFinishToday(reviewMapper.selectCount(wrapper1));
            for(int i = 7; i>=1; i--) {
                List<String> time = getTimeRange(i);
                QueryWrapper<Review> wrapper2 = new QueryWrapper<>();
                wrapper2.between("review_time", time.get(0), time.get(1)).eq("user_id",reviewId).ne("result", -1);
                reviewStaticVo.getFinishSeven().add(reviewMapper.selectCount(wrapper2));
            }
        }
        return JsonResponse.success(reviewStaticVo);
    }

    @Override
    public Boolean generateNotice(Long articleId) {
        log.info("articleId：{}", articleId);
        SubNoticeVo subNoticeVo = articleMapper.getNoticeById(articleId);
        log.info("{}",subNoticeVo);
        QueryWrapper<Subscribe> wrapper = new QueryWrapper<>();
        wrapper.select("user_id").eq("category_id",subNoticeVo.getCategoryId());
        List<Long> userIds = subscribeMapper.selectList(wrapper).stream().map(Subscribe::getUserId).collect(Collectors.toList());
        log.info("{}",userIds);
        if(userIds.size() == 0){
            return false;
        }
        if(subscribeService.generateNotice(subNoticeVo, userIds)){
            return true;
        }
        return false;
    }

    public List<String> getTimeRange(Integer day){
        LocalDateTime currentDateTime = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);

        // 计算8天前的日期时间
        LocalDateTime start = currentDateTime.minusDays(day);

        // 获取昨天的日期时间
        LocalDateTime end = currentDateTime.minusDays(day-1);

        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 格式化时间范围的起始和结束
        String startFormatter = start.format(formatter);
        String endFormatter = end.format(formatter);
        List<String> list = new ArrayList<>();
        list.add(startFormatter);
        list.add(endFormatter);
        return list;
    }
}
